﻿#include <CommunicationMethod.h>

extern QMap<int,QVariantMap> expLogInfo;
extern QString currentStep;
extern QMap<int,QVariantMap> expSendList;
extern int expStatus;
extern int expStep;
extern QString expName;
extern double totalExpTime;
extern QString stepOperatingInfo;
extern QString expConsumablesType;
extern QStringList runningList;
extern bool haveConsumables;

/**
 * @brief 构造函数
 */
CommunicationMethod::CommunicationMethod()
{
    log = Loghelper::getInstance();
    udpClient = UdpClient::getInstance();
}

/**
 * @brief 析构函数
 */
CommunicationMethod::~CommunicationMethod()
{}

//启动实验
Q_INVOKABLE  void CommunicationMethod:: startExperiment(){

    //exe_config 0实验信息 1注射器 2阀门 3转盘 4等待 5检测器 6循环 7跳过 8盖盖 9气泵
    udpClient=UdpClient::getInstance();
    expSendList.clear();

    QSqlDatabase db = dbHelper::openConnection();
    QSqlQuery query(db);

    QString id;
    QString sql;
    QString code=common->getItemCode("3",expConsumablesType);
    sql=QString("Select Id From exe_config Where value_1='%1' and value_2='%2' and type='0'").arg(expName,code);

    //获取实验ID
    query.exec(sql);
    while (query.next()) {
        id=query.value("ID").toString();
    }

    QMap<QString,QVariantMap> circleStepList;

    sql=QString("Select * From exe_config Where Id='%1' and type='6' order by Step ").arg(id);
    query.exec(sql);
    while (query.next())
    {
        QVariantMap map;
        map["Begin"]=query.value("value_1").toString();
        map["End"]=query.value("value_2").toString();
        map["CircleNum"]=query.value("value_3").toString();
        map["Step"]=query.value("step").toString();
        circleStepList.insert(query.value("value_1").toString(),map);
    }

    QList<QVariantMap> exeConfigList;

    sql=QString("Select * From exe_Config Where id='%1' and Type<>'0' order by Step").arg(id);
    query.exec(sql);
    while (query.next()) {
        QVariantMap map;
        for (int i = 0; i < query.record().count(); ++i) {
            map[query.record().fieldName(i)] = query.value(i);
        }
        exeConfigList.append(map);
    }
    totalExpTime=0;
    int step=1;
    for(int i=0;i<exeConfigList.length();i++){
        if(circleStepList.contains(exeConfigList[i].value("step").toString()))
        {
            QVariantMap beginMap;
            beginMap["Type"]="1";//0 正常执行(Info发送指令) 1循环(开始循环,结束循环) 2 跳过("") 3等待(等待时长)
            beginMap["Step"]=circleStepList[exeConfigList[i].value("step").toString()]["Step"].toString();
            beginMap["Info"]="开始循环";
            expSendList.insert(step,beginMap);
            step++;

            QString startNum=circleStepList[exeConfigList[i].value("step").toString()]["Begin"].toString();
            QString endNum= circleStepList[exeConfigList[i].value("step").toString()]["End"].toString();
            int circleNum= circleStepList[exeConfigList[i].value("step").toString()]["CircleNum"].toInt();

            for(int a=0;a<circleNum;a++){
                for(int m=startNum.toInt();m<=endNum.toInt();m++)
                {
                    QVariantMap map;
                    QString type=exeConfigList[m-1].value("type").toString();

                    if(type=="1")//注射器
                    {
                        QString sql=QString("Select InsideDiameter,ReductionRatio,ScrewLead,CircleStep From SyringeMaintenance Where ConsumablesTypes='%1' and Id='%2'").arg(code,exeConfigList[m-1].value("value_1").toString());
                        query.exec(sql);
                        double InsideDiameter,ScrewLead,CircleStep;
                        QString ReductionRatio;
                        while (query.next()) {
                            InsideDiameter=query.value("InsideDiameter").toDouble();
                            ReductionRatio=query.value("ReductionRatio").toString();
                            ScrewLead=query.value("ScrewLead").toDouble();
                            CircleStep=query.value("CircleStep").toDouble();
                        }
                        double speed=exeConfigList[m-1].value("value_8").toDouble();

                        // 速度单位:ml/分
                        if(exeConfigList[m-1].value("value_9")=="mL/Min")
                        {
                            speed=common->minToSecond(QString::number(speed),QString::number(InsideDiameter)).toDouble();
                        }

                        QStringList reList=ReductionRatio.split(':');

                        double stepNum=exeConfigList[m-1].value("value_6").toDouble()/ScrewLead*CircleStep*reList[1].toDouble();
                        double time=exeConfigList[m-1].value("value_6").toDouble()/speed;
                        double stepNumber = stepNum/time;
                        map["Type"]="0";//0 正常执行(Info发送指令) 1循环(开始循环,结束循环) 2 跳过("") 3等待(等待时长) 4检测器
                        map["Step"]=exeConfigList[m-1].value("step").toString();
                        map["Info"]=CommCommand::I().getSyring(QString::number(step),exeConfigList[m-1].value("value_1").toString(),exeConfigList[m-1].value("value_4").toString(),QString::number(stepNumber),QString::number(stepNum));
                        totalExpTime+=time;

                        expSendList.insert(step,map);
                        step++;
                    }
                    else if(type=="2")//阀门
                    {
                        map["Type"]="0";
                        map["Step"]=exeConfigList[m-1].value("step").toString();
                        map["Info"]= CommCommand::I().getValve(QString::number(step),exeConfigList[m-1].value("value_1").toString(),exeConfigList[m-1].value("value_2").toString());
                        totalExpTime+=0.3;

                        expSendList.insert(step,map);
                        step++;
                    }
                    else if(type=="3")//转盘
                    {
                        map["Type"]="0";
                        map["Step"]=exeConfigList[m-1].value("Step").toString();
                        map["Info"]=CommCommand::I().getTurntable(QString::number(step),exeConfigList[m-1].value("value_1").toString());

                        totalExpTime+=1;

                        expSendList.insert(step,map);
                        step++;
                    }
                    else if(type=="4")//检测器
                    {
                        map["Type"]="4";
                        map["Step"]=exeConfigList[m-1].value("step").toString();
                        map["Info"]="";
                    }
                    else if(type=="5")//等待
                    {
                        map["Type"]="3";
                        map["Step"]=exeConfigList[m-1].value("Step").toString();
                        map["Info"]=exeConfigList[m-1].value("Value_1").toString();
                        totalExpTime+=exeConfigList[m-1].value("Value_1").toDouble();

                        expSendList.insert(step,map);
                        step++;
                    }
                    else if(type=="7")//跳过
                    {
                        for(int n=0;n<=exeConfigList[m-1].value("Value_1").toInt();n++)
                        {
                            QVariantMap map;
                            map["Type"]="2";//0 正常执行(Info发送指令) 1循环(开始循环,结束循环) 2 跳过("") 3等待(等待时长)
                            map["Step"]=QString::number(exeConfigList[m-1].value("Step").toInt()+n);
                            map["Info"]="";
                            expSendList.insert(step,map);
                            step++;
                        }
                        m=exeConfigList[m-1].value("Step").toInt()+exeConfigList[m-1].value("Value_1").toInt();
                    }
                    else if(type=="8")//盖盖
                    {
                        if(exeConfigList[m-1].value("value_1").toString()=="是")
                        {
                            map["Type"]="0";
                            map["Step"]=exeConfigList[m-1].value("step").toString();
                            map["Info"]=CommCommand::I().coverTheLid(QString::number(step));
                            expSendList.insert(step,map);
                            totalExpTime+=1.22;

                        }
                        step++;
                    }
                }

                QVariantMap map;
                map["Type"]="1";//0 正常执行(Info发送指令) 1循环(开始循环,结束循环) 2 跳过("") 3等待(等待时长)
                map["Step"]=circleStepList[exeConfigList[i].value("step").toString()]["Step"].toString();
                map["Info"]=QString("第%1次循环完成").arg(QString::number(a+1));
                expSendList.insert(step,map);
                step++;
            }
            i=circleStepList[exeConfigList[i].value("step").toString()]["Step"].toInt()-1;
        }
        else {
            QString type=exeConfigList[i].value("type").toString();
            QVariantMap map;

            if(type=="1")//注射器
            {
                QString sql=QString("Select InsideDiameter,ReductionRatio,ScrewLead,CircleStep From SyringeMaintenance Where ConsumablesTypes='%1' and Id='%2'").arg(code,exeConfigList[i].value("value_1").toString());
                query.exec(sql);
                double InsideDiameter,ScrewLead,CircleStep;
                QString ReductionRatio;
                while (query.next()) {
                    InsideDiameter=query.value("InsideDiameter").toDouble();
                    ReductionRatio=query.value("ReductionRatio").toString();
                    ScrewLead=query.value("ScrewLead").toDouble();
                    CircleStep=query.value("CircleStep").toDouble();
                }
                double speed=exeConfigList[i].value("value_8").toDouble();

                if(exeConfigList[i].value("value_9")=="mL/Min")// 速度单位:ml/分
                {
                    speed=common->minToSecond(QString::number(speed),QString::number(InsideDiameter)).toDouble();
                }

                QStringList reList=ReductionRatio.split(':');

                double stepNum=exeConfigList[i].value("value_6").toDouble()/ScrewLead*CircleStep*reList[1].toDouble();
                double time=exeConfigList[i].value("value_6").toDouble()/speed;
                double stepNumber= stepNum/time;
                map["Type"]="0";
                if(exeConfigList.length()>i+1){
                    if(exeConfigList[i+1].value("type").toInt()==4)
                    {
                        map["Type"]="7";
                    }
                    else{
                        map["Type"]="0";
                    }
                }

                map["Step"]=exeConfigList[i].value("step").toString();
                map["Info"]=CommCommand::I().getSyring(QString::number(step),exeConfigList[i].value("value_1").toString(),exeConfigList[i].value("value_4").toString(),QString::number(stepNumber),QString::number(stepNum));
                totalExpTime+=time;

                expSendList.insert(step,map);
                step++;
            }
            else if(type=="2")//阀门
            {
                map["Type"]="0";
                map["Step"]=exeConfigList[i].value("step").toString();
                map["Info"]= CommCommand::I().getValve(QString::number(step),exeConfigList[i].value("value_1").toString(),exeConfigList[i].value("value_2").toString());

                totalExpTime+=0.3;

                expSendList.insert(step,map);
                step++;
            }
            else if(type=="3")//转盘
            {
                map["Type"]="0";
                map["Step"]=exeConfigList[i].value("step").toString();
                map["Info"]=CommCommand::I().getTurntable(QString::number(step),exeConfigList[i].value("value_1").toString());

                totalExpTime+=1;

                expSendList.insert(step,map);
                step++;
            }
            else if(type=="4")//检测器
            {
                map["Type"]="4";
                map["Step"]=exeConfigList[i].value("step").toString();
                map["Info"]=exeConfigList[i].value("value_1").toString()+","+exeConfigList[i].value("value_2").toString();
                expSendList.insert(step,map);
                step++;
            }
            else if(type=="5")//等待
            {
                map["Type"]="3";
                map["Step"]=exeConfigList[i].value("step").toString();
                map["Info"]=exeConfigList[i].value("value_1").toString();
                totalExpTime+=exeConfigList[i].value("value_1").toDouble();

                expSendList.insert(step,map);
                step++;
            }
            else if(type=="7")//跳过
            {
                for(int m=0;m<=exeConfigList[i].value("value_1").toInt();m++)
                {
                    QVariantMap map;
                    map["Type"]="2";//0 正常执行(Info发送指令) 1循环(开始循环,结束循环) 2 跳过("") 3等待(等待时长)
                    map["Step"]=QString::number(exeConfigList[i].value("step").toInt()+m);
                    map["Info"]="";
                    expSendList.insert(step,map);
                    step++;
                }
                i=exeConfigList[i].value("step").toInt()+exeConfigList[i].value("value_1").toInt()-1;
            }
            else if(type=="8")//盖盖
            {
                if(exeConfigList[i].value("value_1").toString()=="是"){
                    map["Type"]="0";
                    map["Step"]=exeConfigList[i].value("step").toString();
                    map["Info"]=CommCommand::I().coverTheLid(QString::number(step));
                    expSendList.insert(step,map);
                    totalExpTime+=1.22;

                }
                step++;
            }
        }
    }
    udpClient->ClientSendingData(common->GetSendData( CommCommand::I().startExperiment()));
}

//实验中操作 6急停 // 2停止 暂停 继续上位机控制 延时上位机控制
Q_INVOKABLE void CommunicationMethod::stopExperiment(int order)
{
    if(order==2)//停止
    {
        udpClient->ClientSendingData(common->GetSendData( CommCommand::I().stopExperiment()));
    }
    else if(order==3)//暂停
    {
        expStatus=2;
        udpClient->ClientSendingData(common->GetSendData( CommCommand::I().pauseExperiment()));
    }
    else if(order==4)//继续
    {
        expStatus=1;
        udpClient->ClientSendingData(common->GetSendData( CommCommand::I().continueExperiment()));
    }
    else if(order==5)//复位
    {
        udpClient->ClientSendingData(common->GetSendData( CommCommand::I().resetExpPos("0","0")));
    }
    else if(order==6)//急停
    {
        expStatus=0;
        udpClient=UdpClient::getInstance();
        QString info="62 00 00 3A 00 0A 03 00 E7 2F 55 AA";
        udpClient->ClientSendingData(common->GetSendData(info));
    }
    else if(order ==7)//故障继续
    {
        ExperimentThread::I().run();
    }
}

Q_INVOKABLE void CommunicationMethod::stepOperatingSimulation(QString type,QList<QString> operation)
{
    if(type=="1")//注射器
    {
        if(runningList.contains(operation[1]))
        {
            QMLSignal::I().emitSendSyringRunMsg("1",operation[1]);
            return;
        }

        QString code= common->getItemCode("3",operation[0]);

        QSqlDatabase db = dbHelper::openConnection();
        QSqlQuery query(db);

        QString sql=QString("Select Count(*) Num From SyringeMaintenance Where ConsumablesTypes='%1' and id='%2'").arg(code,operation[1]);
        query.exec(sql);
        int Num;
        while (query.next()) {
            Num=query.value("Num").toInt();
        }
        if(Num>0){
            runningList.append(operation[1]);

            sql=QString("Select InsideDiameter,ReductionRatio,ScrewLead,CircleStep From SyringeMaintenance Where ConsumablesTypes='%1' and id='%2'").arg(code,operation[1]);
            query.exec(sql);
            double InsideDiameter,ScrewLead,CircleStep;
            QString ReductionRatio;
            while (query.next()) {
                InsideDiameter=query.value("InsideDiameter").toDouble();
                ReductionRatio=query.value("ReductionRatio").toString();
                ScrewLead=query.value("ScrewLead").toDouble();
                CircleStep=query.value("CircleStep").toDouble();
            }
            double speed=operation[8].toDouble();
            if(operation[9]=="mL/Min")// 速度单位:ml/分
            {
                speed=common->minToSecond(QString::number(speed),QString::number(InsideDiameter)).toDouble();
            }
            QStringList reList=ReductionRatio.split(':');
            double stepNum=operation[6].toDouble()/ScrewLead*CircleStep*reList[1].toDouble();
            double time=operation[6].toDouble()/speed;
            double stepNumber= stepNum/time;

            stepOperatingInfo=CommCommand::I().getSyring(operation[1],operation[1],operation[4],QString::number(stepNumber),QString::number(stepNum));
            udpClient->ClientSendingData(common->GetSendData(stepOperatingInfo));
        }
        else{
            QMLSignal::I().emitSyringDataLack();
        }
    }
    else if(type=="2")//阀门
    {
        stepOperatingInfo=CommCommand::I().getValve(QString::number(8),operation[0],operation[1]);
        udpClient->ClientSendingData(common->GetSendData(stepOperatingInfo));
    }
    else if(type=="3")//转盘
    {
        if(runningList.contains("7"))
        {
            QMLSignal::I().emitSendSyringRunMsg("1","7");
            return;
        }
        runningList.append("7");
        stepOperatingInfo=CommCommand::I().getTurntable("7",operation[0]);
        udpClient->ClientSendingData(common->GetSendData(stepOperatingInfo));
    }
    else if(type=="8")//盖盖
    {
        if(operation[0]=="是" )
        {
            stepOperatingInfo=CommCommand::I().coverTheLid(QString::number(8));
            udpClient->ClientSendingData(common->GetSendData(stepOperatingInfo));
        }
    }
}

Q_INVOKABLE void CommunicationMethod::setConsumable(QString name)
{
    QString code= common->getItemCode("3",name);
    QString info= CommCommand::I().resetExpPos(code,0);
    udpClient->ClientSendingData(common->GetSendData(info));
}

Q_INVOKABLE int CommunicationMethod::checkConsumablesSyring(QString consumablesName)
{
    //    if(!haveConsumables)
    //    {
    //        return -1;
    //    }
    QSqlDatabase db = dbHelper::openConnection();
    QSqlQuery query(db);
    QString code=common->getItemCode("3",consumablesName);
    QString sql=QString("Select count(*) As Num From SyringeMaintenance Where ConsumablesTypes='%1'").arg(code);
    query.exec(sql);
    int result=0;
    while (query.next())
    {
        result=query.value("Num").toInt();
    }

    if(result==0){
        return 1;
    }
    else{
        sql=QString("Select count(*) As Num From SyringeMaintenance Where ConsumablesTypes='%1' and (InsideDiameter is ''  or InitialPosition  is '' or ReductionRatio is '' or ScrewLead is '' or CircleStep is '' )").arg(code);
        query.exec(sql);
        while (query.next())
        {
            result=query.value("Num").toInt();
        }
    }
    return  result;
}

